package com.zhulong.saas.cloud.gateway.gwfilter;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zhulong.common.basic.exception.BasicErrorCode;
import com.zhulong.common.basic.exception.SystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.Base64;

@Component
public class AddAuthInfoFilter implements GlobalFilter, Ordered {

    private static final Logger log = LoggerFactory.getLogger(AddAuthInfoFilter.class);

    @Value("${gw.userInfo.key:zl_userInfo}")
    private String userInfoKey;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        return ReactiveSecurityContextHolder.getContext()
                .filter(c -> c.getAuthentication() != null)
                .map(SecurityContext::getAuthentication)
                .flatMap(c -> {
                    log.debug("增加认证的head的参数");
                    Object principal = c.getPrincipal();
                    String secHead = toSecHeadStr(principal);
                    log.debug("增加的认证参数为：{}，值为：{}", userInfoKey, secHead);
                    ServerHttpRequest request = exchange.getRequest().mutate().header(userInfoKey, secHead).build();
                    return chain.filter(exchange.mutate().request(request).build());
                })
                .switchIfEmpty(chain.filter(exchange));
    }

    private String toSecHeadStr(Object secDetails) {
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String secDetailStr = objectMapper.writeValueAsString(secDetails);
            return Base64.getEncoder().encodeToString(secDetailStr.getBytes("UTF-8"));
        } catch (JsonProcessingException | UnsupportedEncodingException e) {
            throw new SystemException(BasicErrorCode.SYS_ERROR, "认证信息获取错误");
        }
    }

    @Override
    public int getOrder() {
        return 100;
    }
}
